﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace FerrScript
{
    delegate ScriptValue ScriptFunctionDelegate(CompilerInstruction[] aArgs);

    class ScriptFunction
    {
        #region Fields
        private  ScriptFunctionDelegate function;
        private  MethodInfo             methodInfo;
        private  object                 methodObject;
        internal string                 functionName;
        #endregion

        #region Constructors
        public ScriptFunction(string aName, ScriptFunctionDelegate aDelegate)
        {
            functionName = aName;
            function     = aDelegate;
        }
        public ScriptFunction(string aName, object aClass, string aMethodName)
        {
            functionName = aName;

            // set this up for calling a method belonging to a class instance
            methodObject   = aClass;
            Type classType = aClass.GetType();
            methodInfo     = classType.GetMethod(aMethodName);

            // error checking
            if (methodInfo == null)
                throw new Exception("Unable to find the method specified! - " + aMethodName);
        }
        public ScriptFunction(string aName, Type aClassType, string aMethodName)
        {
            functionName = aName;

            // set this up for calling a static class
            methodObject = null;
            methodInfo   = aClassType.GetMethod(aMethodName);

            // error checking
            if (methodInfo == null)
                throw new Exception("Unable to find the method specified! - " + aMethodName);
        }
        #endregion

        #region Methods
        public ScriptValue Call(CompilerInstruction[] aArgs)
        {
            if (function != null)
                return function(aArgs);
            else
            {
                // set up the argument list
                object[] args = new object[aArgs.Length];
                for (int i=0;i<aArgs.Length;i++)
                {
                    args[i] = aArgs[i].Evaluate().value;
                }

                // call the method
                return new ScriptValue(methodInfo.Invoke(methodObject, args));
            }
        }
        #endregion
    }
}
